﻿Imports System.Data.OleDb

Public Class SamengesteldeArtikelsDal

    Private Const SELECT_HOOFDARTIKEL_IDS As String = "SELECT DISTINCT ArtikelId From SamengesteldeArtikels"

    Private Const SELECT_DEELARTIKEL_IDS As String = "SELECT DISTINCT DeelArtikelId From SamengesteldeArtikels"

    Private Const SELECT_HOOFDARTIKELS As String = "SELECT DISTINCT Artikels.Id, Artikels.Artikelcode, " & _
        "Artikels.Omschrijving, Artikels.Barcode, Artikels.Prijs " & _
        "FROM SamengesteldeArtikels INNER JOIN Artikels ON SamengesteldeArtikels.ArtikelId = Artikels.Id"

    Private Const SELECT_DEELARTIKELS As String = "SELECT Artikels.Id, Artikels.Artikelcode, Artikels.Omschrijving, " & _
        "Artikels.Barcode, Artikels.Prijs, SamengesteldeArtikels.Aantal " & _
        "FROM SamengesteldeArtikels INNER JOIN Artikels ON SamengesteldeArtikels.DeelArtikelId = Artikels.Id " & _
        "WHERE SamengesteldeArtikels.ArtikelId=?"

    Private Const DELETE_SAMENGESTELDE_ARTIKELS As String = "DELETE * FROM SamengesteldeArtikels WHERE ArtikelId=?"

    Private Const INSERT_SAMENGESTELDE_ARTIKELS As String = "INSERT INTO SamengesteldeArtikels (ArtikelId, DeelartikelId, Aantal) " & _
        "VALUES (?,?,?)"

    Public Shared Function GetHoofdartikelIds() As List(Of Integer)
        Dim list As New List(Of Integer)
        Dim conn As New OleDbConnection(My.Settings.fairshopConnectionString)
        Try
            conn.Open()
            Dim cm As New OleDbCommand(SELECT_HOOFDARTIKEL_IDS, conn)
            Dim dr As OleDbDataReader = cm.ExecuteReader()
            While dr.Read()
                list.Add(Convert.ToInt32(dr("ArtikelId")))
            End While
        Finally
            conn.Close()
        End Try
        Return list
    End Function

    Public Shared Function GetDeelartikelIds() As List(Of Integer)
        Dim list As New List(Of Integer)
        Dim conn As New OleDbConnection(My.Settings.fairshopConnectionString)
        Try
            conn.Open()
            Dim cm As New OleDbCommand(SELECT_DEELARTIKEL_IDS, conn)
            Dim dr As OleDbDataReader = cm.ExecuteReader()
            While dr.Read()
                list.Add(Convert.ToInt32(dr("DeelArtikelId")))
            End While
        Finally
            conn.Close()
        End Try
        Return list
    End Function

    Public Shared Sub FillHoofdartikels(ByVal ds As ArtikelLijstDataSet)
        Dim conn As New OleDbConnection(My.Settings.fairshopConnectionString)
        Try
            Dim cm As New OleDbCommand(SELECT_HOOFDARTIKELS, conn)
            Dim da As New OleDbDataAdapter(cm)
            da.Fill(ds, ds.Artikels.TableName)
        Finally
            conn.Close()
        End Try
    End Sub

    Public Shared Sub FillDeelartikels(ByVal hoofdartikelId As Integer, ByVal ds As ArtikelLijstDataSet)
        Dim conn As New OleDbConnection(My.Settings.fairshopConnectionString)
        Try
            Dim cm As New OleDbCommand(SELECT_DEELARTIKELS, conn)
            cm.Parameters.AddWithValue("?", hoofdartikelId)
            Dim da As New OleDbDataAdapter(cm)
            ds.Artikels.Clear()
            da.Fill(ds, ds.Artikels.TableName)
        Finally
            conn.Close()
        End Try
    End Sub

    ''' <summary>
    ''' Werk samengestelde artikels bij.
    ''' Deze methode verwijdert alleen de samenstellingen van de hoofdartikels die in de dataset verwijderd zijn 
    ''' (RowState=Deleted) uit de databanktabel
    ''' </summary>
    ''' <param name="hoofdartikelsDataset"></param>
    Public Shared Sub UpdateSamengesteldeArtikels(ByVal hoofdartikelsDataset As ArtikelLijstDataSet)
        ' TODO: unit test maken
        If (Not hoofdartikelsDataset.HasChanges()) Then Return
        Dim conn As New OleDbConnection(My.Settings.fairshopConnectionString)
        Try
            conn.Open()
            For Each row As ArtikelLijstDataSet.ArtikelsRow In hoofdartikelsDataset.Artikels
                If (row.RowState = DataRowState.Deleted) Then
                    Dim cmDelete As New OleDbCommand(DELETE_SAMENGESTELDE_ARTIKELS, conn)
                    cmDelete.Parameters.AddWithValue("?", row.Id)
                    ' verwijder alles van het hoofdartikel
                    cmDelete.ExecuteNonQuery()
                    row.AcceptChanges()
                End If
            Next
        Finally
            conn.Close()
        End Try
    End Sub

    ''' <summary>
    ''' Werk samengestelde artikels bij.
    ''' Deze methode verwijdert alle deelartikels van het artikel met id hoofdartikelId,
    ''' en voegt dan alle deelartikels uit de meegegeven dataset weer toe aan dat artikel.
    ''' </summary>
    ''' <param name="hoofdartikelId"></param>
    ''' <param name="deelartikelsDataset"></param>
    Public Shared Sub UpdateSamengesteldeArtikels(ByVal hoofdartikelId As Integer, ByVal deelartikelsDataset As ArtikelLijstDataSet)
        ' TODO: unit test maken
        If (Not deelartikelsDataset.HasChanges()) Then Return
        Dim conn As New OleDbConnection(My.Settings.fairshopConnectionString)
        Try
            conn.Open()
            Dim cmDelete As New OleDbCommand(DELETE_SAMENGESTELDE_ARTIKELS, conn)
            ' verwijder alle deelartikels van het hoofdartikel
            cmDelete.Parameters.AddWithValue("?", hoofdartikelId)
            cmDelete.ExecuteNonQuery()
            For Each row As ArtikelLijstDataSet.ArtikelsRow In deelartikelsDataset.Artikels
                If (row.RowState = DataRowState.Deleted) Then Continue For
                ' voeg nieuw deelartikel toe
                Dim cmInsert As New OleDbCommand(INSERT_SAMENGESTELDE_ARTIKELS, conn)
                cmInsert.Parameters.AddWithValue("?", hoofdartikelId)
                cmInsert.Parameters.AddWithValue("?", row.Id)
                cmInsert.Parameters.AddWithValue("?", row.Aantal)
                cmInsert.ExecuteNonQuery()
                row.AcceptChanges()
            Next
        Finally
            conn.Close()
        End Try
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="barcodeDoos"></param>
    ''' <param name="barcodeArtikel"></param>
    ''' <param name="aantal"></param>
    ''' <returns></returns>
    ''' <remarks>Gebruikt om een volledig nieuwe doos aan te maken</remarks>
    Public Shared Function AddDoos(ByVal barcodeDoos As String, ByVal barcodeArtikel As String, ByVal aantal As Integer) As ArtikelsDataSet.ArtikelsRow
        ' TODO: unit test maken
        Dim artikelRow As ArtikelsDataSet.ArtikelsRow = (From a In Utility.Data.Artikels _
                                                         Where a.Barcode = barcodeArtikel).FirstOrDefault
        If (artikelRow Is Nothing) Then
            Throw New Exception("Artikel niet gevonden")
        End If
        If (From a In Utility.Data.Artikels _
                Where a.Barcode = barcodeDoos).Any() Then
            Throw New Exception("Er bestaat al een artikel met de barcode van de doos")
        End If
        Dim doosArtikelCode As String = Constants.DOOS_PREFIX & "0001"
        Dim vorigeDoosArtikelcode As String = (From a In Utility.Data.Artikels _
                                                Where a.Artikelcode.StartsWith(Constants.DOOS_PREFIX) _
                                                Order By a.Artikelcode Descending _
                                                Select a.Artikelcode).FirstOrDefault
        If (vorigeDoosArtikelcode IsNot Nothing) Then
            doosArtikelCode = String.Format("{0}{1:D4}", Constants.DOOS_PREFIX, CInt(vorigeDoosArtikelcode.Substring(Constants.DOOS_PREFIX.Length)) + 1)
        End If

        ' maak een artikel aan voor de doos
        Dim doosRow As ArtikelsDataSet.ArtikelsRow = Utility.Data.Artikels.NewArtikelsRow()
        doosRow.Omschrijving = String.Format("Doos {0} x {1}", aantal, artikelRow.OmschrijvingIngekort(60))
        doosRow.Barcode = barcodeDoos
        doosRow.Prijs = 0D
        doosRow.BTW = 0D
        doosRow.KortingLeverancier = 0D
        doosRow.IsLeeggoed = False
        doosRow.Verkoopbaar = artikelRow.Verkoopbaar
        doosRow.Inkoopprijs = 0D
        doosRow.IsCheque = False
        doosRow.StatiegeldEuro = 0D
        doosRow.VerwachteVoorraad = 0
        doosRow.Voorraad = 0
        doosRow.IdLeverancier = artikelRow.IdLeverancier
        doosRow.IdCategorie = artikelRow.IdCategorie
        doosRow.AantalPerVerpakking = 0
        doosRow.Artikelcode = doosArtikelCode
        'doosRow.DatumToegevoegd = DateTime.Now()
        Utility.Data.Artikels.AddArtikelsRow(doosRow)
        Dal.ArtikelToevoegen(doosRow)

        ' maak het samengesteld artikel aan
        Dim sds As New ArtikelLijstDataSet()
        Dim sar As ArtikelLijstDataSet.ArtikelsRow = sds.Artikels.NewArtikelsRow()
        sar.Id = artikelRow.Id
        sar.Aantal = aantal
        sds.Artikels.AddArtikelsRow(sar)
        UpdateSamengesteldeArtikels(doosRow.Id, sds)
        Return doosRow
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="doosRow"></param>
    ''' <param name="barcodeArtikel"></param>
    ''' <param name="aantalArtikelsPerDoos"></param>
    ''' <param name="aantalDozen"></param>
    ''' <remarks>Gebruikt voor dozen gemaakt vanuit BeheerArtikelForm</remarks>
    Public Shared Sub AddDozen(ByVal doosRow As ArtikelsDataSet.ArtikelsRow, ByVal barcodeArtikel As String, _
                              ByVal aantalArtikelsPerDoos As Integer, ByVal aantalDozen As Integer)
        ' TODO: unit test maken
        If (doosRow.RowState <> DataRowState.Added) Then
            Throw New Exception("Bij het toevoegen van een doos mag de doos nog niet bewaard zijn")
        End If
        Dim artikelRow As ArtikelsDataSet.ArtikelsRow = (From a In Utility.Data.Artikels _
                                                         Where a.Barcode = barcodeArtikel).FirstOrDefault
        If (artikelRow Is Nothing) Then
            Throw New Exception("Artikel niet gevonden")
        End If
        Dim doosArtikelCode As String = Constants.DOOS_PREFIX & "0001"
        Dim vorigeDoosArtikelcode As String = (From a In Utility.Data.Artikels _
                                                Where a.Artikelcode.StartsWith(Constants.DOOS_PREFIX) _
                                                Order By a.Artikelcode Descending _
                                                Select a.Artikelcode).FirstOrDefault
        If (vorigeDoosArtikelcode IsNot Nothing) Then
            doosArtikelCode = String.Format("{0}{1:D4}", Constants.DOOS_PREFIX, CInt(vorigeDoosArtikelcode.Substring(Constants.DOOS_PREFIX.Length)) + 1)
        End If

        ' vul de doosRow op
        doosRow.Omschrijving = String.Format("Doos {0} x {1}", aantalArtikelsPerDoos, artikelRow.OmschrijvingIngekort(60))
        doosRow.Prijs = 0D
        doosRow.BTW = 0D
        doosRow.KortingLeverancier = 0D
        doosRow.IsLeeggoed = False
        doosRow.Verkoopbaar = artikelRow.Verkoopbaar
        doosRow.Inkoopprijs = 0D
        doosRow.IsCheque = False
        doosRow.StatiegeldEuro = 0D
        doosRow.VerwachteVoorraad = 0
        doosRow.Voorraad = aantalDozen ' nodig?
        doosRow.IdLeverancier = artikelRow.IdLeverancier
        doosRow.IdCategorie = artikelRow.IdCategorie
        doosRow.AantalPerVerpakking = 0
        doosRow.Artikelcode = doosArtikelCode
        'doosRow.DatumToegevoegd = DateTime.Now()
        Dal.ArtikelToevoegen(doosRow)

        ' Bij leveringen kan het zijn dat de doosRow uit een aparte dataset komt (voor leveringsdetails)
        If (doosRow.Table IsNot Utility.Data.Artikels) Then
            ' doos ook toevoegen aan Utility.Data zodat ze bij volgende scan gevonden kan worden
            Utility.Data.Artikels.ImportRow(doosRow)
        End If

        '' pas de verwachte voorraad van het artikel aan '' NIET HIER DOEN, caller moet dit doen.
        'artikelRow.VerwachteVoorraad += (aantalArtikelsPerDoos * aantalDozen)
        'Dal.Bijwerken(Utility.Data.Artikels)

        ' maak het samengesteld artikel aan
        Dim sds As New ArtikelLijstDataSet()
        Dim sar As ArtikelLijstDataSet.ArtikelsRow = sds.Artikels.NewArtikelsRow()
        sar.Id = artikelRow.Id
        sar.Aantal = aantalArtikelsPerDoos
        sds.Artikels.AddArtikelsRow(sar)
        UpdateSamengesteldeArtikels(doosRow.Id, sds)
    End Sub

    Public Shared Function PrepareSamengesteldeArtikelsDataSet() As SamengesteldeArtikelsDataSet
        Using conn As New OleDbConnection(My.Settings.fairshopConnectionString)
            Try
                conn.Open()
                Dim ds As New SamengesteldeArtikelsDataSet
                Dim samengesteldeArtikelsAdapter As New SamengesteldeArtikelsDataSetTableAdapters.SamengesteldeArtikelsTableAdapter
                samengesteldeArtikelsAdapter.Connection = conn
                samengesteldeArtikelsAdapter.Fill(ds.SamengesteldeArtikels)
                ds.AcceptChanges()
                Return ds
            Finally
                conn.Close()
            End Try
        End Using
    End Function

End Class
